/*
 * Copyright (C) Francisco Morero Peyrona. All rights reserved.
 *
 * This software is published under the terms of Open Source
 * License version 1.1, a copy of which has been included with this
 * distribution in the License.txt file.
 */

package jdbcmanager.diagram;

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

import jdbcmanager.swing.table.*;
import jdbcmanager.diagram.swing.*;
import jdbcmanager.dbtools.datatypes.*;

/**
 * This shows the table structure using a JTable.
 * 
 * @author Francisco Morero Peyrona
 */
final class JGridTableColumns extends JxTableVector
{
   // Column positions in table
   private final static int nKEY  = 0;
   private final static int nNAME = 1;
   private final static int nTYPE = 2;
   private final static int nSIZE = 3;   // Size or number of digist before decimal separator
   private final static int nSCAL = 4;   // Scale: number of digits after decimal separator
   private final static int nNULL = 5;   // Is nullable?
   private final static int nAUTO = 6;   // Is autoincrement?
   
   static final short nSHOW_MODE_COMPACT  = 0;
   static final short nSHOW_MODE_EXPANDED = 1;
   
   private short nShowMode;

   private TableColumn colType = null;
   private TableColumn colSize = null;
   private TableColumn colScal = null;
   private TableColumn colNull = null;
   private TableColumn colAuto = null;   

   //-------------------------------------------------------------------------//
   
   JGridTableColumns()
   {
      this( null );
   }
   
   JGridTableColumns( TableColumnDefinition[] aColumn )
   {
      setFields( aColumn );
      init();
   }

   void setFields( TableColumnDefinition[] aColumn )
   {
      setData( aColumn );
   }

   TableColumnDefinition[] getColumns()
   {
      TableColumnDefinition[] aRet = new TableColumnDefinition[ this.vData.size() ];

      this.vData.copyInto( aRet );

      return aRet;
   }

   /**
    * The point where the JRelation line has to connect with the table
    *
    * @param sField The JRelation key field (either primary or foreign)
    * @return Point Where to connect
    */
   Point getRowPoint( JTableSpider board, String sField )
   {
      Rectangle rect      = getVisibleRect();
      Point     point     = rect.getLocation();
      int       nFirstRow = rowAtPoint( point ) + 1;          // It is 1, not 0 based
      point.setLocation( rect.getX() + rect.getWidth(), rect.getY() + rect.getHeight() );
      int       nLastRow  = rowAtPoint( point ) + 1;          // It is 1, not 0 based;
      int       nRow      = getRowFromFieldName( sField );    // The row that we are checking now
      int       nYpos     = 0;
      
      if( nLastRow == 0 )
         nLastRow = Integer.MAX_VALUE;  // Even last row is visible
      
      if( nRow < nFirstRow )
      {
         nYpos = 1;
      }
      else if( nRow > nLastRow )
      {
         nYpos = (int) board.getSize().getHeight() - JBoard.nFRAME_TITLE_HEIGHT - JBoard.nFRAME_BORDER_HEIGHT + 2;
      }
      else   // nRow is visible
      {
         int nRowHeight = getRowHeight() + (getRowMargin() / 2);
         int nHeight    = getTableHeader().getHeight() + (nRowHeight * (nRow - nFirstRow + 1));
         
         nYpos = nHeight - (nRowHeight / 3); // To place the line (2 pixels width) in the middle of the cell
      }

      return new Point( 0, nYpos );
   }

   /**
    * Height of the table when all rows are shown.
    * @return Height of the table when all rows are shown
    */
   int getTotalHeight()
   {
      int nHeader = getTableHeader().getHeight();
      int nTable  = (getRowCount()+1) * (getRowHeight() + getRowMargin());

      return nHeader + nTable;
   }

   /**
    * Shows [all | 2 first] columns
    * @param b New status
    */
   void setShowMode( short nMode )
   {
      this.nShowMode = nMode;

      setShowHorizontalLines( nMode == nSHOW_MODE_EXPANDED );

      getColumnModel().getColumn( nKEY  ).setPreferredWidth( 16 );
      getColumnModel().getColumn( nNAME ).setPreferredWidth( 88 );

      if( nMode == nSHOW_MODE_COMPACT )
      {
         removeColumn( this.colAuto );
         removeColumn( this.colNull );
         removeColumn( this.colScal );
         removeColumn( this.colSize );
         removeColumn( this.colType );
      }
      else
      {
         addColumn( this.colType );
         addColumn( this.colSize );
         addColumn( this.colScal );
         addColumn( this.colNull );
         addColumn( this.colAuto );

         this.colType.setPreferredWidth( 74 );
         this.colSize.setPreferredWidth( 35 );
         this.colScal.setPreferredWidth( 28 );
         this.colNull.setPreferredWidth( 47 );
         this.colAuto.setPreferredWidth( 47 );
      }
   }

   /**
    * Return show mode status
    * @return Show mode status
    */
   short getShowMode()
   {
      return this.nShowMode;
   }

   //-------------------------------------------------------------------------//

   private int getRowFromFieldName( String sColumnName )
   {
      TableColumnDefinition[] aColumn = getColumns();

      for( int n = 0; n < aColumn.length; n++ )
         if( aColumn[n].getName().equals( sColumnName ) )
            return n+1;   // +1 because it is 0 based

      throw new ArrayIndexOutOfBoundsException( sColumnName +": field does not exist. This should not happen." );
   }
   
   //-------------------------------------------------------------------------//

   private void init()
   {
      Font font = new Font( "Dialog", Font.PLAIN, 10 );

      setFont( font );
      getTableHeader().setFont( font );
      setAutoResizeMode( AUTO_RESIZE_OFF );
      setShowVerticalLines( false );
      setBackground( Color.white );

      setModel( new ThisTableModel() );
      setHead( new String[] { "", "Field Name", "Type Name", "Size", "Dec", "Nullable", "AutoInc" } );
      
      this.colType = getColumnModel().getColumn( nTYPE );
      this.colSize = getColumnModel().getColumn( nSIZE );
      this.colScal = getColumnModel().getColumn( nSCAL );
      this.colNull = getColumnModel().getColumn( nNULL );
      this.colAuto = getColumnModel().getColumn( nAUTO );
      
      setShowMode( nSHOW_MODE_COMPACT );
   }

   //---------------------------------------------------------------//
   // INNER CLASS: TABLE MODEL
   //---------------------------------------------------------------//
   private final class ThisTableModel extends JxTableVector.TableVectorModel
   {
      private ImageIcon imgKey   = new ImageIcon( JGridTableColumns.class.getResource( "images/key.gif"   ) );
      private ImageIcon imgNoKey = new ImageIcon( JGridTableColumns.class.getResource( "images/nokey.gif" ) );
      
      public Object getValueAt( int nRow, int nCol )
      {
         TableColumnDefinition column = (TableColumnDefinition) JGridTableColumns.this.vData.get( nRow );
         Object oRet;

         switch( nCol )
         {
            case nKEY:  oRet = column.isPrimaryKey() ? this.imgKey : this.imgNoKey;  break;
            case nNAME: oRet = column.getName();                                     break;
            case nTYPE: oRet = column.getType().getName();                           break;
            case nSIZE: oRet = new Integer( column.getSize() );                      break;
            case nSCAL: oRet = new Integer( column.getScale() );                     break;
            case nNULL: oRet = new Boolean( column.isNullable() );                   break;
            case nAUTO: oRet = new Boolean( column.isAutoIncrement() );              break;
            default:    oRet = "<Error>";  // Avoid to create this String instance if there is no error
         }
         
         return oRet;
      }

      public void setValueAt( Object value, int nRow, int nCol )
      {
         // As it is not editable --> nothing to do
      }
   }
}